﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows;

using TJDevHouse.Starcraft.Game;

namespace TJDevHouse.Starcraft.MapAnalyser.MapDrawing
{
	class PathfindingTestsMapLayer : MapLayer
	{
		private MapDisplay Display { get; set; }

		private WalkTile StartTile { get; set; }
		private WalkTile EndTile { get; set; }

		//the tile highlights
		private Shape _startRect;
		private Shape _endRect;

		private MapAnalysisController Analysis { get; set; }


		protected override void RenderLayer(MapDisplay display)
		{
			Display = display;
			Analysis = MapAnalysisController.GetMapAnalysisController(display.Map);
			LayerCanvas.Background = new SolidColorBrush(Color.FromArgb(0, 0, 0, 0));
			LayerCanvas.MouseUp += new System.Windows.Input.MouseButtonEventHandler(LayerCanvas_MouseUp);
		}

		void LayerCanvas_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
			Point point = e.GetPosition(LayerCanvas);
			SelectATile(point);
		}

		/// <summary>
		/// Do the main logic for selecting a tile to select the to/from tile
		/// </summary>
		/// <param name="point"></param>
		private void SelectATile(Point point)
		{

			//get the selected tile
			WalkTile wt = Display.GetWalkTileFromPoint(point);

			//check the selected tile is ok
			if (!wt.IsWalkable)
			{
				MessageBox.Show("That's not a walkable tile...", "Invalid Tile");
				return;
			}

			//selecting the first tile will null the end tile
			if (StartTile == null || EndTile != null)
			{
				//selecting start tile
				SelectStartTile(wt);
			}
			else
			{
				//selecting target tile
				SelectToTile(wt);
			}
		}

		/// <summary>
		/// Mark this tile as the start of the route.
		/// 
		/// Will clear the To tile and do any other maintanence
		/// needed
		/// </summary>
		/// <param name="wt"></param>
		private void SelectStartTile(WalkTile wt)
		{
			RemoveShapeFromCanvas(_startRect);
			RemoveShapeFromCanvas(_endRect);

			StartTile = wt;
			EndTile = null;
			_startRect = HighlightTile(wt, Colors.Aquamarine);
		}

		/// <summary>
		/// Mark this tile as the end of the route.
		/// 
		/// Will check whether the requested tile is actually
		/// walkable to from the start tile
		/// </summary>
		/// <param name="wt"></param>
		private void SelectToTile(WalkTile wt)
		{
			RemoveShapeFromCanvas(_endRect);

			//check the target is walkable to from the start tile
			if (!Analysis.WalkabilityAnalyser.IsTileWalkableFrom(wt, StartTile))
			{
				MessageBox.Show("That tile is not walkable from the first tile", "Can't walk to there");
				return;
			}

			EndTile = wt;
			_endRect = HighlightTile(wt, Colors.Red);

			//run the pathfinding
			try
			{
				MapPath path = Analysis.PathFinder.FindPath(StartTile, EndTile);


				
				//draw the tiles processed in the route
				int step = 0;
				foreach (PathFindingNode node in path.ProcessedNodes)
				{
					WalkTile nt = Display.Map.GetWalkTile(node.X, node.Y);

					//fade the color from black to bright red going through the tried nodes

					Color color = Color.FromScRgb(1, step / path.ProcessedNodes.Count, 1, 1) ;

					HighlightTile(nt, color, step.ToString());
					step++;
				}
				

				//draw the path
				foreach (WalkTile tile in path.Route)
				{
					HighlightTile(tile, Colors.White);
				}
			}
			catch (Exception e)
			{
				Console.WriteLine(e.ToString());
			}

		}

		/// <summary>
		/// Removes the given shape from the layer canvas.
		/// 
		/// Used when clearing previous start/end positions, etc.
		/// </summary>
		/// <param name="shape"></param>
		private void RemoveShapeFromCanvas(Shape shape)
		{
			if (shape != null)
			{
				shape.Visibility = Visibility.Hidden;
				LayerCanvas.Children.Remove(shape);
			}
		}

		/// <summary>
		/// Highlight the given tile on the map.
		/// 
		/// Will return the generated rectangle.
		/// </summary>
		/// <param name="wt"></param>
		/// <returns></returns>
		private Shape HighlightTile(WalkTile wt, Color color)
		{

			SolidColorBrush brush = new SolidColorBrush(color);
			Rectangle tileSquare = new Rectangle();
			tileSquare.Fill = brush;
			tileSquare.Stroke = brush;
			tileSquare.Height = Display.WalkTileSize;
			tileSquare.Width = Display.WalkTileSize;
			Display.PositionElementByWalkTile(tileSquare, wt.X, wt.Y);

			LayerCanvas.Children.Add(tileSquare);
			return tileSquare;
		}

		/// <summary>
		/// Highlight a tile and add a tooltip
		/// </summary>
		/// <param name="wt"></param>
		/// <param name="color"></param>
		/// <param name="tooltip"></param>
		/// <returns></returns>
		private Shape HighlightTile(WalkTile wt, Color color, string tooltip)
		{
			Shape tile = HighlightTile(wt, color);
			tile.ToolTip = tooltip;
			return tile;
		}
	}
}
